/*
* atlas_clapack.cpp
* 
* Copyright (c) 2003-2004, .NET Analytics Project. All rights reserved.
*/
#ifdef _WINDOWS
	#ifndef VC_EXTRALEAN
		#define VC_EXTRALEAN
	#endif
	#include "windows.h"
#endif

extern "C" {
#ifdef WRAP_VECLIB
	#include <vecLib/vecLib.h>
#else
	#include "clapack.h"
#endif
}

#ifdef _WINDOWS
	#define DLLEXPORT __declspec( dllexport )
#else
	#define DLLEXPORT
#endif

extern "C" {

	inline char getTchar(const CBLAS_TRANSPOSE trans){
		char cTrans;
		switch( trans ){
			case  CblasNoTrans : cTrans = 'N';
				break;
			case  CblasTrans : cTrans = 'T';
				break;
			case  CblasConjTrans : cTrans = 'C';
				break;
		}
		return cTrans;
	}

	inline char getSchar(const CBLAS_SIDE side){
		char cSide;
		switch( side ){
			case  CblasLeft : cSide= 'L';
				break;
			case  CblasRight : cSide = 'R';
				break;
		}
		return cSide;
	}

	inline char getUchar(const CBLAS_UPLO uplo){
		char cUplo;
		switch( uplo ){
			case CblasLower : cUplo = 'L';
				break;
			case CblasUpper : cUplo = 'U';
				break;
		}
		return cUplo;
	}

	integer DLLEXPORT dna_lapack_sormbr( integer block_size, char vect, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, float* a, integer lda, float* tau, float* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		float* work = new float[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormbr_(&vect, &sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_dormbr( integer block_size, char vect, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, double* a, integer lda, double* tau, double* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		double* work = new double[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormbr_(&vect, &sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_cunmbr( integer block_size, char vect, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmbr_(&vect, &sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_zunmbr( integer block_size,  char vect, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmbr_(&vect, &sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_cungbr(integer block_size, char vect, integer m, integer n, integer k, complex* a, integer lda, complex* tau ){
		integer info;
		integer lwork = min(m,n)*block_size;
		complex* work = new complex[lwork];
		cungbr_(&vect, &m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_zungbr(integer block_size, char vect, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau ){
		integer info;
		integer lwork = min(m,n)*block_size;
		doublecomplex* work = new doublecomplex[lwork];
		zungbr_(&vect, &m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_sorgbr(integer block_size, char vect, integer m, integer n, integer k, float* a, integer lda, float* tau ){
		integer info;
		integer lwork = min(m,n)*block_size;
		float* work = new float[lwork];
		sorgbr_(&vect, &m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_dorgbr(integer block_size, char vect, integer m, integer n, integer k, double* a, integer lda, double* tau ){
		integer info;
		integer lwork = min(m,n)*block_size;
		double* work = new double[lwork];
		dorgbr_(&vect, &m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_sgebrd(integer block_size,integer m, integer n, float* a, integer lda, float* d, float* e, float* tauq, float* taup ){
		integer info;
		integer lwork = (m + n)*block_size;
		float* work = new float[lwork];
		sgebrd_(&m, &n, a, &lda, d, e, tauq, taup, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_dgebrd(integer block_size,integer m, integer n, double* a, integer lda, double* d, double* e, double* tauq, double* taup ){
		integer info;
		integer lwork = (m + n)*block_size;
		double* work = new double[lwork];
		dgebrd_(&m, &n, a, &lda, d, e, tauq, taup, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_cgebrd(integer block_size,integer m, integer n, complex* a, integer lda, float* d, float* e, complex* tauq, complex* taup ){
		integer info;
		integer lwork = (m + n)*block_size;
		complex* work = new complex[lwork];
		cgebrd_(&m, &n, a, &lda, d, e, tauq, taup, work, &lwork, &info);
		delete[] work;
		return info;
	}

	integer DLLEXPORT dna_lapack_zgebrd(integer block_size,integer m, integer n, doublecomplex* a, integer lda, double* d, double* e, doublecomplex* tauq, doublecomplex* taup ){
		integer info;
		integer lwork = (m + n)*block_size;
		doublecomplex* work = new doublecomplex[lwork];
		zgebrd_(&m, &n, a, &lda, d, e, tauq, taup, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sgeqp3(integer m, integer n, float* a, integer lda, integer* jpvt, float* tau ){
		integer info;
		integer lwork = 3*n+1;
		float* work = new float[lwork];
		sgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgeqp3(integer m, integer n, double* a, integer lda, integer* jpvt, double* tau ){
		integer info;
		integer lwork = 3*n+1;
		double* work = new double[lwork];
		dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgeqp3(integer m, integer n, complex* a, integer lda, integer* jpvt, complex* tau ){
		integer info;
		integer lwork = n+1;
		complex* work = new complex[lwork];
		float* rwork = new float[2*n];
		cgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, rwork, &info);
		delete[] work;
		delete[] rwork;
		return info;
	}

	int DLLEXPORT dna_lapack_zgeqp3(integer m, integer n, doublecomplex* a, integer lda, integer* jpvt, doublecomplex* tau ){
		integer info;
		integer lwork = n+1;
		doublecomplex* work = new doublecomplex[lwork];
		double* rwork = new double[2*n];
		zgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, rwork, &info);
		delete[] work;
		delete[] rwork;
		return info;
	}
	
	int DLLEXPORT dna_lapack_sormqr(integer block_size,CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, float* a, integer lda, float* tau, float* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		float* work = new float[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormqr_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dormqr(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, double* a, integer lda, double* tau, double* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		double* work = new double[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormqr_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunmqr(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmqr_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunmqr(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmqr_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}
	
	int DLLEXPORT dna_lapack_sorgqr(integer block_size, integer m, integer n, integer k, float* a, integer lda, float* tau ){
		integer info;
		integer lwork = block_size*n;
		float* work = new float[lwork];
		sorgqr_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dorgqr( integer block_size, integer m, integer n, integer k, double* a, integer lda, double* tau ){
		integer info;
		integer lwork = block_size*n;
		double* work = new double[lwork];
		dorgqr_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cungqr( integer block_size, integer m, integer n, integer k, complex* a, integer lda, complex* tau ){
		integer info;
		integer lwork = block_size*n;
		complex* work = new complex[lwork];
		cungqr_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zungqr( integer block_size, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau ){
		integer info;
		integer lwork = block_size*n;
		doublecomplex* work = new doublecomplex[lwork];
		zungqr_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sgetrs(const CBLAS_TRANSPOSE  trans, int n, int nrhs, float* a, int lda, int* ipiv, float* b,int ldb ){
		return clapack_sgetrs(CblasColMajor, trans, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_dgetrs(const CBLAS_TRANSPOSE  trans, int n, int nrhs, double* a, int lda, int* ipiv, double* b,int ldb ){
		return clapack_dgetrs(CblasColMajor, trans, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_cgetrs(const CBLAS_TRANSPOSE  trans, int n, int nrhs, void* a, int lda, int* ipiv, void* b,int ldb ){
		return clapack_cgetrs(CblasColMajor, trans, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_zgetrs(const CBLAS_TRANSPOSE  trans, int n, int nrhs, void* a, int lda, int* ipiv, void* b,int ldb ){
		return clapack_zgetrs(CblasColMajor, trans, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_sgesv(int n, int nrhs, float* a, int lda, int* ipiv, float* b, int ldb ){
		return clapack_sgesv(CblasColMajor, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_dgesv(int n, int nrhs, double* a, int lda, int* ipiv, double* b, int ldb ){
		return clapack_dgesv(CblasColMajor, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_cgesv(int n, int nrhs, void* a, int lda, int* ipiv, void* b, int ldb ){
		return clapack_cgesv(CblasColMajor, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_zgesv(int n, int nrhs, void* a, int lda, int* ipiv, void* b, int ldb ){
		return clapack_zgesv(CblasColMajor, n, nrhs, a, lda, ipiv, b, ldb);
	}

	int DLLEXPORT dna_lapack_sgetri( integer block_size, int n, float* a, int lda, int* ipiv ){
		return clapack_sgetri(CblasColMajor,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_dgetri( integer block_size, int n, double* a, int lda, int* ipiv ){
		return clapack_dgetri(CblasColMajor,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_cgetri( integer block_size, int n, void* a, int lda, int* ipiv ){
		return clapack_cgetri(CblasColMajor,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_zgetri( integer block_size, int n, void* a, int lda, int* ipiv ){
		return clapack_zgetri(CblasColMajor,n,a,lda,ipiv);
	}
	
	int DLLEXPORT dna_lapack_sgetrf(int m, int n, float* a, int lda, int *ipiv){
		return clapack_sgetrf(CblasColMajor,m,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_dgetrf(int m, int n, double *a, int lda, int *ipiv){
		return clapack_dgetrf(CblasColMajor,m,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_cgetrf(int m, int n, void *a, int lda, int *ipiv){
		return clapack_cgetrf(CblasColMajor,m,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_zgetrf(int m, int n, void *a, int lda, int *ipiv){
		return clapack_zgetrf(CblasColMajor,m,n,a,lda,ipiv);
	}

	int DLLEXPORT dna_lapack_spotrf(const CBLAS_UPLO uplo, int n, float *a, int lda){
		return clapack_spotrf(CblasColMajor, uplo, n, a, lda);
	}

	int DLLEXPORT dna_lapack_dpotrf(const CBLAS_UPLO uplo, int n, double *a, int lda) {
		return clapack_dpotrf(CblasColMajor, uplo, n, a, lda);
	}

	int DLLEXPORT dna_lapack_cpotrf(const CBLAS_UPLO uplo, int n, void *a, int lda) {
		return clapack_cpotrf(CblasColMajor, uplo, n, a, lda);
	}

	int DLLEXPORT dna_lapack_zpotrf(const CBLAS_UPLO uplo, int n, void *a, int lda) {
		return clapack_zpotrf(CblasColMajor, uplo, n, a, lda);
	}

	int DLLEXPORT dna_lapack_spotrs(const CBLAS_UPLO uplo, int n, int nrhs, float *a, int lda, float *b, int ldb) {
		return clapack_spotrs(CblasColMajor, uplo, n, nrhs, a, lda, b, ldb);
	}
	
	int DLLEXPORT dna_lapack_dpotrs(const CBLAS_UPLO uplo, int n, int nrhs, double *a, int lda, double *b, int ldb) {
		return clapack_dpotrs(CblasColMajor, uplo, n, nrhs, a, lda, b, ldb);
	}

	int DLLEXPORT dna_lapack_cpotrs(const CBLAS_UPLO uplo, int n, int nrhs, void *a, int lda, void *b, int ldb) {
		return clapack_cpotrs(CblasColMajor, uplo, n, nrhs, a, lda, b, ldb);
	}

	int DLLEXPORT dna_lapack_zpotrs(const CBLAS_UPLO uplo, int n, int nrhs, void *a, int lda, void *b, int ldb) {
		return clapack_zpotrs(CblasColMajor, uplo, n, nrhs, a, lda, b, ldb);
	}

	int DLLEXPORT dna_lapack_spocon(const CBLAS_UPLO uplo, integer n, real *a, integer lda, real anorm, real *rcond) {
		integer info;
		real* work = new real[3*n];
		integer* iwork = new integer[n];
		char uChar = getUchar(uplo);
		spocon_(&uChar, &n, a, &lda, &anorm, rcond, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_dpocon(const CBLAS_UPLO uplo, integer n, doublereal *a, integer lda, doublereal anorm, doublereal *rcond) {
		integer info;
		doublereal* work = new doublereal[3*n];
		integer* iwork = new integer[n];
		char uChar = getUchar(uplo);
		dpocon_(&uChar, &n, a, &lda, &anorm, rcond, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_cpocon(const CBLAS_UPLO uplo, integer n, complex *a, integer lda, real anorm, real *rcond) {
		integer info;
		complex* work = new complex[2*n];
		real* rwork = new real[n];
		char uChar = getUchar(uplo);
		cpocon_(&uChar, &n, a, &lda, &anorm, rcond, work, rwork, &info);
		delete[] work;
		delete[] rwork;
		return info;
	}

	int DLLEXPORT dna_lapack_zpocon(const CBLAS_UPLO uplo, integer n, doublecomplex *a, integer lda, doublereal anorm, doublereal *rcond) {
		integer info;
		doublecomplex* work = new doublecomplex[2*n];
		doublereal* rwork = new doublereal[n];
		char uChar = getUchar(uplo);
		zpocon_(&uChar, &n, a, &lda, &anorm, rcond, work, rwork, &info);
		delete[] work;
		delete[] rwork;
		return info;
	}

	int DLLEXPORT dna_lapack_spotri(const CBLAS_UPLO uplo, integer n, real *a, integer lda) {
		integer info;
		char uChar = getUchar(uplo);
		spotri_(&uChar, &n, a, &lda, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_dpotri(const CBLAS_UPLO uplo, integer n, doublereal *a, integer lda) {
		integer info;
		char uChar = getUchar(uplo);
		dpotri_(&uChar, &n, a, &lda, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_cpotri(const CBLAS_UPLO uplo, integer n, complex *a, integer lda) {
		integer info;
		char uChar = getUchar(uplo);
		cpotri_(&uChar, &n, a, &lda, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_zpotri(const CBLAS_UPLO uplo, integer n, doublecomplex *a, integer lda) {
		integer info;
		char uChar = getUchar(uplo);
		zpotri_(&uChar, &n, a, &lda, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_sgehrd(integer block_size, integer n, integer ilo, integer ihi, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = block_size*n;
		real* work = new real[lwork];
		sgehrd_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgehrd(integer block_size, integer n, integer ilo, integer ihi, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = block_size*n;
		doublereal* work = new doublereal[lwork];
		dgehrd_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgehrd(integer block_size, integer n, integer ilo, integer ihi, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = block_size*n;
		complex* work = new complex[lwork];
		cgehrd_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zgehrd(integer block_size, integer n, integer ilo, integer ihi, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = block_size*n;
		doublecomplex* work = new doublecomplex[lwork];
		zgehrd_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sorghr(integer block_size, integer n, integer ilo, integer ihi, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(ihi-ilo,1)*block_size;
		real* work = new real[lwork];
		sorghr_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dorghr(integer block_size, integer n, integer ilo, integer ihi, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(ihi-ilo,1)*block_size;
		doublereal* work = new doublereal[lwork];
		dorghr_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunghr(integer block_size, integer n, integer ilo, integer ihi, complex *a, integer lda, complex *tau){
		integer info;
		integer lwork = max(ihi-ilo,1)*block_size;
		complex* work = new complex[lwork];
		cunghr_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunghr(integer block_size, integer n, integer ilo, integer ihi, doublecomplex *a, integer lda, doublecomplex *tau){
		integer info;
		integer lwork = max(ihi-ilo,1)*block_size;
		doublecomplex* work = new doublecomplex[lwork];
		zunghr_(&n, &ilo, &ihi, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sormhr(integer block_size, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, integer ilo, integer ihi, real* a, integer lda, real* tau, real* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		real* work = new real[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormhr_(&sChar, &tChar, &m, &n, &ilo, &ihi, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dormhr(integer block_size, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, integer ilo, integer ihi, doublereal* a, integer lda, doublereal* tau, doublereal* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublereal* work = new doublereal[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormhr_(&sChar, &tChar, &m, &n, &ilo, &ihi, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunmhr(integer block_size, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, integer ilo, integer ihi, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmhr_(&sChar, &tChar, &m, &n, &ilo, &ihi, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunmhr(integer block_size, CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, integer ilo, integer ihi, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmhr_(&sChar, &tChar, &m, &n, &ilo, &ihi, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	/*
	// TODO: As we might need to define a new enum for FACT. 
	int DLLEXPORT dna_lapack_sgesvx() {
		
	}
	int DLLEXPORT dna_lapack_dgesvx() {
		
	}
	int DLLEXPORT dna_lapack_cgesvx() {
		
	}
	int DLLEXPORT dna_lapack_zgesvx() {
		
	}
	*/
	int DLLEXPORT dna_lapack_sgeequ(integer m, integer n, real *a, integer lda, real *r, real *c, real *rowcnd, real *colcnd, real *amax){
		integer info;
		sgeequ_(&m, &n, a, &lda, r, c, rowcnd, colcnd, amax, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_dgeequ(integer m, integer n, doublereal *a, integer lda, doublereal *r, doublereal *c, doublereal *rowcnd, doublereal *colcnd, doublereal *amax){
		integer info;
		dgeequ_(&m, &n, a, &lda, r, c, rowcnd, colcnd, amax, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_cgeequ(integer m, integer n, complex *a, integer lda, real *r, real *c, real *rowcnd, real *colcnd, real *amax){
		integer info;
		cgeequ_(&m, &n, a, &lda, r, c, rowcnd, colcnd, amax, &info);
		return info;
	}

	int DLLEXPORT dna_lapack_zgeequ(integer m, integer n, doublecomplex *a, integer lda, doublereal *r, doublereal *c, doublereal *rowcnd, doublereal *colcnd, doublereal *amax){
		integer info;
		zgeequ_(&m, &n, a, &lda, r, c, rowcnd, colcnd, amax, &info);
		return info;
	}

	/*
	// TODO: Need enum for norm
	int DLLEXPORT dna_lapack_sgecon() {
		
	}
	int DLLEXPORT dna_lapack_dgecon() {
		
	}
	int DLLEXPORT dna_lapack_cgecon() {
		
	}
	int DLLEXPORT dna_lapack_zgecon() {
		
	}
	*/

	int DLLEXPORT dna_lapack_sgerfs(const CBLAS_TRANSPOSE trans, integer n, integer nrhs, real *a, integer lda, real *af, integer ldaf, integer *ipiv, real *b, integer ldb, real *x, integer ldx, real *ferr, real *berr){
		integer info;
		real *work = new real[3*n];
		integer *iwork = new integer[n];
		char tChar = getTchar(trans);
		sgerfs_(&tChar, &n, &nrhs, a, &lda, af, &ldaf, ipiv, b, &ldb, x, &ldx, ferr, berr, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_dgerfs(const CBLAS_TRANSPOSE trans, integer n, integer nrhs, doublereal *a, integer lda, doublereal *af, integer ldaf, integer *ipiv, doublereal *b, integer ldb, doublereal *x, integer ldx, doublereal *ferr, doublereal *berr){
		integer info;
		doublereal *work = new doublereal[3*n];
		integer *iwork = new integer[n];
		char tChar = getTchar(trans);
		dgerfs_(&tChar, &n, &nrhs, a, &lda, af, &ldaf, ipiv, b, &ldb, x, &ldx, ferr, berr, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_cgerfs(const CBLAS_TRANSPOSE trans, integer n, integer nrhs, complex *a, integer lda, complex *af, integer ldaf, integer *ipiv, complex *b, integer ldb, complex *x, integer ldx, real *ferr, real *berr){
		integer info;
		complex *work = new complex[3*n];
		real *iwork = new real[n];
		char tChar = getTchar(trans);
		cgerfs_(&tChar, &n, &nrhs, a, &lda, af, &ldaf, ipiv, b, &ldb, x, &ldx, ferr, berr, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_zgerfs(const CBLAS_TRANSPOSE trans, integer n, integer nrhs, doublecomplex *a, integer lda, doublecomplex *af, integer ldaf, integer *ipiv, doublecomplex *b, integer ldb, doublecomplex *x, integer ldx, doublereal *ferr, doublereal *berr){
		integer info;
		doublecomplex *work = new doublecomplex[3*n];
		doublereal *iwork = new doublereal[n];
		char tChar = getTchar(trans);
		zgerfs_(&tChar, &n, &nrhs, a, &lda, af, &ldaf, ipiv, b, &ldb, x, &ldx, ferr, berr, work, iwork, &info);
		delete[] work;
		delete[] iwork;
		return info;
	}

	int DLLEXPORT dna_lapack_sgerqf(integer block_size, integer m, integer n, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		real *work = new real[lwork];
		sgerqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgerqf(integer block_size, integer m, integer n, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublereal *work = new doublereal[lwork];
		dgerqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgerqf(integer block_size, integer m, integer n, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		complex *work = new complex[lwork];
		cgerqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zgerqf(integer block_size, integer m, integer n, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublecomplex *work = new doublecomplex[lwork];
		zgerqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sorgrq(integer block_size, integer m, integer n, integer k, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		real *work = new real[lwork];
		sorgrq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dorgrq(integer block_size, integer m, integer n, integer k, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublereal *work = new doublereal[lwork];
		dorgrq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cungrq(integer block_size, integer m, integer n, integer k, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		complex *work = new complex[lwork];
		cungrq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zungrq(integer block_size, integer m, integer n, integer k, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublecomplex *work = new doublecomplex[lwork];
		zungrq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sormrq(integer block_size,CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, float* a, integer lda, float* tau, float* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		float* work = new float[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormrq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dormrq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, double* a, integer lda, double* tau, double* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		double* work = new double[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormrq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunmrq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmrq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunmrq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmrq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}
	
	int DLLEXPORT dna_lapack_sgelqf(integer block_size, integer m, integer n, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		real *work = new real[lwork];
		sgelqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgelqf(integer block_size, integer m, integer n, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublereal *work = new doublereal[lwork];
		dgelqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgelqf(integer block_size, integer m, integer n, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		complex *work = new complex[lwork];
		cgelqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zgelqf(integer block_size, integer m, integer n, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublecomplex *work = new doublecomplex[lwork];
		zgelqf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sorglq(integer block_size, integer m, integer n, integer k, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		real *work = new real[lwork];
		sorglq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dorglq(integer block_size, integer m, integer n, integer k, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublereal *work = new doublereal[lwork];
		dorglq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunglq(integer block_size, integer m, integer n, integer k, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		complex *work = new complex[lwork];
		cunglq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunglq(integer block_size, integer m, integer n, integer k, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*m);
		doublecomplex *work = new doublecomplex[lwork];
		zunglq_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sormlq(integer block_size,CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, float* a, integer lda, float* tau, float* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		float* work = new float[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormlq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dormlq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, double* a, integer lda, double* tau, double* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		double* work = new double[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormlq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunmlq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmlq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunmlq(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmlq_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}
	
	int DLLEXPORT dna_lapack_sgeqlf(integer block_size, integer m, integer n, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		real *work = new real[lwork];
		sgeqlf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgeqlf(integer block_size, integer m, integer n, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublereal *work = new doublereal[lwork];
		dgeqlf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgeqlf(integer block_size, integer m, integer n, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		complex *work = new complex[lwork];
		cgeqlf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zgeqlf(integer block_size, integer m, integer n, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublecomplex *work = new doublecomplex[lwork];
		zgeqlf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sorgql(integer block_size, integer m, integer n, integer k, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		real *work = new real[lwork];
		sorgql_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dorgql(integer block_size, integer m, integer n, integer k, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublereal *work = new doublereal[lwork];
		dorgql_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cungql(integer block_size, integer m, integer n, integer k, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		complex *work = new complex[lwork];
		cungql_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zungql(integer block_size, integer m, integer n, integer k, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublecomplex *work = new doublecomplex[lwork];
		zungql_(&m, &n, &k, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_sormql(integer block_size,CBLAS_SIDE side, CBLAS_TRANSPOSE trans, integer m, integer n, integer k, float* a, integer lda, float* tau, float* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		float* work = new float[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		sormql_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dormql(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, double* a, integer lda, double* tau, double* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		double* work = new double[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		dormql_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cunmql(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, complex* a, integer lda, complex* tau, complex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		complex* work = new complex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		cunmql_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zunmql(integer block_size,const CBLAS_SIDE side, const CBLAS_TRANSPOSE trans, integer m, integer n, integer k, doublecomplex* a, integer lda, doublecomplex* tau, doublecomplex* c, integer ldc ){
		integer info;
		integer lwork;
		if( side == CblasLeft ){
			lwork = block_size*n;
		}else{
			lwork = block_size*m;
		}
		doublecomplex* work = new doublecomplex[lwork];
		char tChar = getTchar(trans);
		char sChar = getSchar(side);
		zunmql_(&sChar, &tChar, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
		delete[] work;
		return info;
	}

    int DLLEXPORT dna_lapack_sbdsqr(CBLAS_UPLO uplo, integer n, integer ncvt, integer nru, integer ncc, float* d, float* e, float* vt, integer ldvt, float* u, integer ldu, float* c, integer ldc ){
        integer info;
        integer lwork;
        if( ncvt == nru == ncc == 0 ){
            lwork = max(1,2*n);
        }else{
            lwork = max(1,4*(n-1));
        }

        float* work = new float[lwork];
        char uChar = getUchar(uplo);
        sbdsqr_(&uChar, &n, &ncvt, &nru, &ncc, d, e, vt, &ldvt, u, &ldu, c, &ldc, work, &info);
        delete[] work;
        return info;
    }

    int DLLEXPORT dna_lapack_dbdsqr(CBLAS_UPLO uplo, integer n, integer ncvt, integer nru, integer ncc, double* d, double* e, double* vt, integer ldvt, double* u, integer ldu, double* c, integer ldc ){
        integer info;
        integer lwork;
        if( ncvt == nru == ncc == 0 ){
            lwork = max(1,2*n);
        }else{
            lwork = max(1,4*(n-1));
        }

        double* work = new double[lwork];
        char uChar = getUchar(uplo);
        dbdsqr_(&uChar, &n, &ncvt, &nru, &ncc, d, e, vt, &ldvt, u, &ldu, c, &ldc, work, &info);
        delete[] work;
        return info;
    }

    int DLLEXPORT dna_lapack_cbdsqr(CBLAS_UPLO uplo, integer n, integer ncvt, integer nru, integer ncc, float* d, float* e, complex* vt, integer ldvt, complex* u, integer ldu, complex* c, integer ldc ){
        integer info;
        integer lwork;
        if( ncvt == nru == ncc == 0 ){
            lwork = max(1,2*n);
        }else{
            lwork = max(1,4*(n-1));
        }

        float* work = new float[lwork];
        char uChar = getUchar(uplo);
        cbdsqr_(&uChar, &n, &ncvt, &nru, &ncc, d, e, vt, &ldvt, u, &ldu, c, &ldc, work, &info);
        delete[] work;
        return info;
    }

    int DLLEXPORT dna_lapack_zbdsqr(CBLAS_UPLO uplo, integer n, integer ncvt, integer nru, integer ncc, double* d, double* e, doublecomplex* vt, integer ldvt, doublecomplex* u, integer ldu, doublecomplex* c, integer ldc ){
        integer info;
        integer lwork;
        if( ncvt == nru == ncc == 0 ){
            lwork = max(1,2*n);
        }else{
            lwork = max(1,4*(n-1));
        }

        double* work = new double[lwork];
        char uChar = getUchar(uplo);
        zbdsqr_(&uChar, &n, &ncvt, &nru, &ncc, d, e, vt, &ldvt, u, &ldu, c, &ldc, work, &info);
        delete[] work;
        return info;
    }

    integer DLLEXPORT dna_lapack_sgesvd(integer m, integer n, float* a, integer lda, float* s, float* u, integer ldu, float* vt, integer ldvt ){
        integer info;
        integer lwork = max(3*min(m,n)+max(m,n), 5*min(m,n));
        float* work = new float[lwork];
        char A = 'A';
        char S = 'S';
        sgesvd_( &S, &A, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info );
        delete[] work;
        return info;
    }

    integer DLLEXPORT dna_lapack_dgesvd(integer m, integer n, double* a, integer lda, double* s, double* u, integer ldu, double* vt, integer ldvt ){
        integer info;
        integer lwork = max(3*min(m,n)+max(m,n), 5*min(m,n));
        double* work = new double[lwork];
        char A = 'A';
        char S = 'S';
        dgesvd_( &S, &A, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, &info );
        delete[] work;
        return info;
    }

    //for some reason this isn't in clapack.h
    extern "C"{
        integer cgesvd_( char*, char*, integer*, integer*, complex*, integer*, real*, complex *, integer*, 
                 complex*, integer*, complex*, integer*, real*, integer*);
    }
    integer DLLEXPORT dna_lapack_cgesvd(integer m, integer n, complex* a, integer lda, float* s, complex* u, integer ldu, complex* vt, integer ldvt ){
        integer info;
        integer lwork = 2*min(m,n)+max(m,n);
        float* rwork = new float[max(1, 5*min(m,n))];
        complex* work = new complex[lwork];
        char A = 'A';
        char S = 'S';
        cgesvd_( &S, &A, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, &info );
        delete[] work;
        return info;
    }

    //for some reason this isn't in clapack.h
    extern "C"{
        integer zgesvd_( char*, char*, integer*, integer*, doublecomplex*, integer*, doublereal*, doublecomplex *, integer*, 
                 doublecomplex*, integer*, doublecomplex*, integer*, doublereal*, integer*);
    }
    integer DLLEXPORT dna_lapack_zgesvd(integer m, integer n, doublecomplex* a, integer lda, double* s, doublecomplex* u, integer ldu, doublecomplex* vt, integer ldvt ){
        integer info;
        integer lwork = 2*min(m,n)+max(m,n);
        double* rwork = new double[max(1, 5*min(m,n))];
        doublecomplex* work = new doublecomplex[lwork];
        char A = 'A';
        char S = 'S';
        zgesvd_( &S, &A, &m, &n, a, &lda, s, u, &ldu, vt, &ldvt, work, &lwork, rwork, &info );
        delete[] work;
        return info;
    }

	int DLLEXPORT dna_lapack_sgeqrf(integer block_size, integer m, integer n, real *a, integer lda, real *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		real *work = new real[lwork];
		sgeqrf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_dgeqrf(integer block_size, integer m, integer n, doublereal *a, integer lda, doublereal *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublereal *work = new doublereal[lwork];
		dgeqrf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_cgeqrf(integer block_size, integer m, integer n, complex *a, integer lda, complex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		complex *work = new complex[lwork];
		cgeqrf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}

	int DLLEXPORT dna_lapack_zgeqrf(integer block_size, integer m, integer n, doublecomplex *a, integer lda, doublecomplex *tau) {
		integer info;
		integer lwork = max(1,block_size*n);
		doublecomplex *work = new doublecomplex[lwork];
		zgeqrf_(&m, &n, a, &lda, tau, work, &lwork, &info);
		delete[] work;
		return info;
	}
	/* 
	//Need enum on job 
	int DLLEXPORT dna_lapack_sgebal(){
	}
	int DLLEXPORT dna_lapack_dgebal(){
	}
	int DLLEXPORT dna_lapack_cgebal(){
	}
	int DLLEXPORT dna_lapack_zgebal(){
	}
	int DLLEXPORT dna_lapack_sgebak(){
	}
	int DLLEXPORT dna_lapack_dgebak(){
	}
	int DLLEXPORT dna_lapack_cgebak(){
	}
	int DLLEXPORT dna_lapack_zgebak(){
	}
	//Need enum on job, compz
	int DLLEXPORT dna_lapack_ssheqr(){
	}
	int DLLEXPORT dna_lapack_dsheqr(){
	}
	int DLLEXPORT dna_lapack_csheqr(){
	}
	int DLLEXPORT dna_lapack_zsheqr(){
	}
	//Need enum on eigensrc, initv
	hsein
	//Need enum on side, howmany, select
	trevc
	//Need enum on job, howmany, select
	trsna
	//Need enum on compute
	trexc
	//Need enum on job, compute, select
	trsen
	//Need enum on isign
	trsyl
	//Need enum on job
	ggbal
	*/
}



